package day0507;

import java.sql.*;

/**
 * User: Allen Zhang
 * Date: 2019-05-07
 * Time: 20:07
 * 如你所见，都是虚胖。
 */
public class OptimisticUnLock {

    //
    String url = "jdbc:mysql://www.vm.com:3306/test?characterEncoding=utf-8&useSSL=false";
    Connection conn = null;
//    Statement stmt=null;

    public static void main(String[] args) {
        //写一个main方法加 N 个线程

        for (int i = 0; i < 20; i++) {
            int num= i%3+1;
            new Thread(new Runnable() {
                @Override
                public void run() {

                    try {
                        OptimisticUnLock t = new OptimisticUnLock();
                        t.buy(num);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
    public void buy(int num) throws Exception {
        //
        Class.forName("com.mysql.jdbc.Driver");
        conn = DriverManager.getConnection(url,"root","root");
        conn.setAutoCommit(false);

        int[] result = getAmount();
        //库存足够
        if(result[0] >=num){

            try {
                updateAmount(num,result[1]);//减库存
                addOrder(num);//下订单

                conn.commit();
            } catch (Exception e) {
                e.printStackTrace();
                conn.rollback();//回滚
                //可以递归 ，继续买。不建议用。
            }

        }else{
            System.out.println("库存不足,召唤师");
        }
        conn.close();
    }

    public int[] getAmount() throws Exception {

        String amountSql = "select amount,version from goods where id=1";
        Statement stmt = conn.createStatement();
        //查库存
        ResultSet rs = stmt.executeQuery(amountSql);
        int[] result = new int[2];
        if(rs.next()){

            result[0] = rs.getInt(1);
            result[1] = rs.getInt(2);
            //不放方法最前面，是因为那时还没有进入事务呢 放在statement 之后
            System.out.println(Thread.currentThread().getName()+"查询库存>>>");
        }
        rs.close();
//        stmt.close();  //为什么有这局就这样？
        return result;
    }

    public int addOrder(int num) throws Exception {

        String sorderSql = "insert into goods_order(amount,name) " +
                "values("+num+",'"+Thread.currentThread().getName()+"')";
        Statement stmt = conn.createStatement();
        int res = stmt.executeUpdate(sorderSql);
        System.out.println(Thread.currentThread().getName()+"添加订单>>>\n>>>");

        stmt.close();
        if(res <=0){
            throw new Exception("添加订单失败");
        }
        return res;
    }

    public int updateAmount(int num,int version) throws Exception {
        String updateSql = "update goods set amount = amount-"+num+
                ",version=version+1 where id=1 and version="+version;
        Statement stmt = conn.createStatement();
        int res = stmt.executeUpdate(updateSql);
        System.out.println(Thread.currentThread().getName()+"更新库存>>>");
        stmt.close();//关闭资源放哪里都行吗？
        if (res <=0){
            throw new Exception("更新库存失败");
        }
        return res;
    }
}
